#include "DBFile.h"

HeapDBFile::HeapDBFile () {	}

HeapDBFile::~HeapDBFile () {
    if (pageType == writing)
        WritePageToFile();

    delete page;
}

int HeapDBFile::Create (char *fpath, fType file_type, void *startup) {

    //create metadata file
	char path[250], c = 'h';
	sprintf (path, "%s.header", fpath);
	FILE *metadata = fopen (path, "w");
	fwrite(&c, 1, sizeof(char), metadata );
	fclose(metadata);

	file.Open(0, fpath);

	page = new Page();
	currentPage = -1;
	currentRecord = 0;
	pageType = reading;
	loadedPage = 0;

    return 1;
}

void HeapDBFile::Load (Schema &f_schema, char *loadpath) {

    if (pageType == writing)
        WritePageToFile();

    FILE *data = fopen(loadpath, "r");
    Record record;

    while (record.SuckNextRecord(&f_schema, data)) {
        Add(record);
    }

    fclose(data);
}

int HeapDBFile::Open (char *f_path) {

    file.Open(1, f_path);

    page = new Page();
	currentPage = -1;
	currentRecord = 0;
	pageType = reading;
	loadedPage = 0;

    return 1;
}

void HeapDBFile::MoveFirst () {

    if (pageType == writing)
        WritePageToFile();

    currentPage = -1;
	currentRecord = 0;
}

int HeapDBFile::Close () {

    if (pageType == writing)
        WritePageToFile();

    file.Close();
    return 1;
}

void HeapDBFile::Add (Record &rec) {

    //if we are reading then get the last page from the file
    if (pageType == reading) {
        pageType = writing;

        if (FileLength() == 0)
            page = new Page();

        else{
            page->EmptyItOut();
            file.GetPage(page, (FileLength() - 1));
            loadedPage = 1;
        }
	}

    //if failed to add the record to the page then add page to file and start a new page
    if (!page->Append(&rec)) {
        file.AddPage(page, FileLength() - loadedPage);
        loadedPage = 0;

        page->EmptyItOut();
        page->Append(&rec);
    }
}

int HeapDBFile::GetNext (Record &fetchme) {

    if (pageType == writing) {
        WritePageToFile();
        pageType = reading;

        file.GetPage(page, currentPage);
        bool eop = false;
        for (int i = 0; i < currentRecord; i++) {
            if (!page->GetFirst(&fetchme)) {
                eop = true;
                break;
            }
        }
    }

    if (currentPage == -1) {
        currentPage++;
        file.GetPage(page, currentPage);
    }

    if (page->GetFirst(&fetchme)) {
        currentRecord++;
        return 1;
    }
    else {
        currentPage++;
        currentRecord = 0;
        if (FileLength() <= currentPage)
            return 0;

        page->EmptyItOut();
        file.GetPage(page, currentPage);
        if (page->GetFirst(&fetchme)) {
            currentRecord++;
            return 1;
        }

        return 0;
    }
}

int HeapDBFile::GetNext (Record &fetchme, CNF &cnf, Record &literal) {

    ComparisonEngine e;
    while (GetNext(fetchme)) {
        if (e.Compare(&fetchme, &literal, &cnf)) {
            return 1;
        }
    }

    return 0;
}

void HeapDBFile::WritePageToFile(){
    if (loadedPage)
        file.AddPage(page, FileLength() - 1);
    else
        file.AddPage(page, FileLength());

    page->EmptyItOut();
    loadedPage = 0;
}
